package com.asen.libcommon.widget

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import com.asen.libcommon.R
import java.util.*

/**
 * @date   : 2020/12/4
 * @author : asenLiang
 * @e-mail : liangAisiSen@163.com
 * @desc   : 状态控件封装
 */
class MultipleStatusView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
    /** 空视图 */
    private var mEmptyView: View? = null,
    private var mEmptyViewResId: Int = 0,
    /** 错误视图 */
    private var mErrorView: View? = null,
    private var mErrorViewResId: Int = 0,
    /** 加载视图 */
    private var mLoadingView: View? = null,
    private var mLoadingViewResId: Int = 0,
    /** 无网络视图 */
    private var mNoNetworkView: View? = null,
    private var mNoNetworkViewResId: Int = 0,
    /** 内容视图 */
    private var mContentView: View? = null,
    private var mContentViewResId: Int = 0,
    /** 视图控制 */
    private var mViewStatus: Int = 0,              // 状态视图
    private var mInflater: LayoutInflater? = null, // 视图加载器
    private var mOnRetryClickListener: OnClickListener? = null, // 视图点击
    /** 保存正在显示的视图id */
    private val mOtherIds: ArrayList<Int>? = ArrayList()
) : RelativeLayout(context, attrs, defStyleAttr) {

    companion object {
        private val DEFAULT_LAYOUT_PARAMS =
            LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)

        private const val STATUS_CONTENT = 0x00
        private const val STATUS_LOADING = 0x01
        private const val STATUS_EMPTY = 0x02
        private const val STATUS_ERROR = 0x03
        private const val STATUS_NO_NETWORK = 0x04
        private const val NULL_RESOURCE_ID = -1
    }

    init {
        val a =
            context.obtainStyledAttributes(attrs, R.styleable.MultipleStatusView, defStyleAttr, 0)
        mEmptyViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_EmptyView,
            R.layout.view_multiple_status_empty
        )
        mErrorViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_ErrorView,
            R.layout.view_multiple_status_error
        )
        mLoadingViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_LoadingView,
            R.layout.view_multiple_status_loading
        )
        mNoNetworkViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_NoNetworkView,
            R.layout.view_multiple_status_no_network
        )
        mContentViewResId =
            a.getResourceId(R.styleable.MultipleStatusView_ContentView, NULL_RESOURCE_ID)
        a.recycle()
        mInflater = LayoutInflater.from(context)
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        showContent()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        clear(mEmptyView, mLoadingView, mErrorView, mNoNetworkView)
        mOtherIds?.clear()
        if (null != mOnRetryClickListener) mOnRetryClickListener = null
        mInflater = null
    }

    /** 获取当前状态 */
    fun getViewStatus(): Int {
        return mViewStatus
    }

    /**
     * 设置重试点击事件
     * @param onRetryClickListener 重试点击事件
     */
    fun setOnRetryClickListener(onRetryClickListener: OnClickListener?) {
        mOnRetryClickListener = onRetryClickListener
    }

    /** 显示空视图 */
    fun showEmpty() {
        showEmpty(mEmptyViewResId, DEFAULT_LAYOUT_PARAMS)
    }

    /**
     * 显示空视图
     * @param layoutId 自定义布局文件
     * @param layoutParams 布局参数
     */
    fun showEmpty(layoutId: Int, layoutParams: ViewGroup.LayoutParams?) {
        showEmpty(inflateView(layoutId), layoutParams)
    }

    /**
     * 显示空视图
     * @param view 自定义视图
     * @param layoutParams 布局参数
     */
    fun showEmpty(view: View?, layoutParams: ViewGroup.LayoutParams?) {
        mViewStatus = STATUS_EMPTY
        if (null == mEmptyView) {
            mEmptyView = view
            val emptyRetryView = mEmptyView?.findViewById<View>(R.id.mEmptyView)
            if (null != mOnRetryClickListener && null != emptyRetryView)
                emptyRetryView.setOnClickListener(mOnRetryClickListener)

            mEmptyView?.id?.let { mOtherIds?.add(it) }
            addView(mEmptyView, 0, layoutParams)
        }
        mEmptyView?.id?.let { showViewById(it) }
    }

    /** 显示错误视图 */
    fun showError() {
        showError(mErrorViewResId, DEFAULT_LAYOUT_PARAMS)
    }

    /**
     * 显示错误视图
     * @param layoutId 自定义布局文件
     * @param layoutParams 布局参数
     */
    fun showError(layoutId: Int, layoutParams: ViewGroup.LayoutParams?) {
        showError(inflateView(layoutId), layoutParams)
    }

    /**
     * 显示错误视图
     * @param view 自定义视图
     * @param layoutParams 布局参数
     */
    fun showError(view: View?, layoutParams: ViewGroup.LayoutParams?) {
        mViewStatus = STATUS_ERROR
        if (null == mErrorView) {
            mErrorView = view
            val errorRetryView = mErrorView?.findViewById<View>(R.id.error_view)
            if (null != mOnRetryClickListener && null != errorRetryView)
                errorRetryView.setOnClickListener(mOnRetryClickListener)

            mErrorView?.id?.let {
                mOtherIds?.add(it)
            }
            addView(mErrorView, 0, layoutParams)
        }
        mErrorView?.id?.let { showViewById(it) }
    }

    /** 显示加载中视图 */
    fun showLoading() {
        showLoading(mLoadingViewResId, DEFAULT_LAYOUT_PARAMS)
    }

    /**
     * 显示加载中视图
     * @param layoutId 自定义布局文件
     * @param layoutParams 布局参数
     */
    fun showLoading(layoutId: Int, layoutParams: ViewGroup.LayoutParams?) {
        showLoading(inflateView(layoutId), layoutParams)
    }

    /**
     * 显示加载中视图
     * @param view 自定义视图
     * @param layoutParams 布局参数
     */
    fun showLoading(view: View?, layoutParams: ViewGroup.LayoutParams?) {
        mViewStatus = STATUS_LOADING
        if (null == mLoadingView) {
            mLoadingView = view
            mLoadingView?.id?.let { mOtherIds?.add(it) }
            addView(mLoadingView, 0, layoutParams)
        }
        mLoadingView?.id?.let { showViewById(it) }
    }

    /** 显示无网络视图 */
    fun showNoNetwork() {
        showNoNetwork(mNoNetworkViewResId, DEFAULT_LAYOUT_PARAMS)
    }

    /**
     * 显示无网络视图
     * @param layoutId 自定义布局文件
     * @param layoutParams 布局参数
     */
    fun showNoNetwork(layoutId: Int, layoutParams: ViewGroup.LayoutParams?) {
        showNoNetwork(inflateView(layoutId), layoutParams)
    }

    /**
     * 显示无网络视图
     * @param view 自定义视图
     * @param layoutParams 布局参数
     */
    fun showNoNetwork(view: View?, layoutParams: ViewGroup.LayoutParams?) {
        mViewStatus = STATUS_NO_NETWORK
        if (null == mNoNetworkView) {
            mNoNetworkView = view
            val noNetworkRetryView = mNoNetworkView?.findViewById<View>(R.id.no_network_view)
            if (null != mOnRetryClickListener && null != noNetworkRetryView)
                noNetworkRetryView.setOnClickListener(mOnRetryClickListener)

            mNoNetworkView?.id?.let { mOtherIds?.add(it) }
            addView(mNoNetworkView, 0, layoutParams)
        }
        mNoNetworkView?.id?.let { showViewById(it) }
    }

    /** 显示内容视图 */
    fun showContent() {
        mViewStatus = STATUS_CONTENT
        if (null == mContentView && mContentViewResId != NULL_RESOURCE_ID) {
            mContentView = mInflater?.inflate(mContentViewResId, null)
            addView(mContentView, 0, DEFAULT_LAYOUT_PARAMS)
        }
        val childCount = childCount
        for (i in 0 until childCount) {
            val view = getChildAt(i)
            view.visibility = if (mOtherIds?.contains(view.id) == true) View.GONE else View.VISIBLE
        }
    }

    private fun inflateView(layoutId: Int): View? = mInflater?.inflate(layoutId, null)

    private fun showViewById(viewId: Int) {
        val childCount = childCount
        for (i in 0 until childCount) {
            val view = getChildAt(i)
            view.visibility = if (view.id == viewId) View.VISIBLE else View.GONE
        }
    }

    private fun checkNull(obj: Any?, hint: String) {
        if (null == obj) throw NullPointerException(hint)
    }

    private fun clear(vararg views: View?) {
        try {
            if (views.isNullOrEmpty()) return
            for (view in views) {
                if (views.isNullOrEmpty()) return
                removeView(view)
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

}